<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">

<title>class Fiddle::Function - fiddle: Ruby Standard Library Documentation</title>


<script src="../js/navigation.js" defer></script>
<script src="../js/search.js" defer></script>
<script src="../js/search_index.js" defer></script>
<script src="../js/searcher.js" defer></script>
<script src="../js/darkfish.js" defer></script>

<script src="../js/jquery-3.2.0.min.js"></script>

<script src="../js/vue.min.js"></script>
<script src="../js/js.cookie.min.js"></script>

<link href="../css/fonts.css" rel="stylesheet">
<link id='rdoccss' href="../css/rdoc.css" rel="stylesheet">
<link href="../css/carbon17.css" rel="stylesheet">

<script type="text/javascript">
  var rdoc_rel_prefix = "../";
  var index_rel_prefix = "../";
  var darkModeCsseHref = "../css/rdoc-dm.css"
  var defaultModeCssHref = "../css/rdoc.css"
  // var cssDarkmode = Cookies.get('darkmode');
  
  if( Cookies.get("darkmode") == "true") {
	$('#rdoccss').attr("href", darkModeCsseHref);
}

//  https://cssdeck.com/blog/simple-jquery-stylesheet-switcher/

document.write('<style type="text/css">body{display:none}</style>');

</script>


</head>
<body id="top" role="document" class="class">
  <!-- this is class.html -->

  <div id='actionbar' >
    <div class='wrapper mdiv'>
      <ul class='grids g0'></ul>
    </div> 
    <!-- VERSION HEADER for 3.3.0.preview2 NOT FOUND -->
  </div> <!-- end action bar -->

  <div class='wrapper hdiv'>

    


    <nav id='vapp' role="navigation">
    <div id="project-navigation">
      <div id="home-section" role="region" title="Quick navigation" class="nav-section">
  <h2><a href="../index.html" rel="home">Home</a></h2>

  <div id="table-of-contents-navigation"  >
    <a href="../table_of_contents.html#pages">Pages</a>
    <a href="../table_of_contents.html#classes">Classes</a>
    <a href="../table_of_contents.html#methods">Methods</a>
  </div>
</div>

      <div id="search-section" role="search" class="project-section initially-hidden">
  <form action="#" method="get" accept-charset="utf-8">
    <div id="search-field-wrapper">
      <input id="search-field" role="combobox" aria-label="Search"
             aria-autocomplete="list" aria-controls="search-results"
             type="text" name="search" placeholder="Search" spellcheck="false"
             title="Type to search, Up and Down to navigate, Enter to load">
    </div>

    <ul id="search-results" aria-label="Search Results"
        aria-busy="false" aria-expanded="false"
        aria-atomic="false" class="initially-hidden"></ul>
  </form>
</div>

    </div>


    
<div class="nav-section">
  <h3>Table of Contents</h3>

  <ul class="link-list" role="directory">
    <li><a href="#class-Fiddle::Function-label-Description">Description</a>
    <li><a href="#class-Fiddle::Function-label-Examples">Examples</a>
    <li><a href="#class-Fiddle::Function-label-27strcpy-27">‘strcpy’</a>
    <li><a href="#class-Fiddle::Function-label-ABI+check">ABI check</a>
  </ul>
</div>


    <button id='toggleThing' @click="toggleNav()" >Show/hide navigation</button>
    <div :class="isOpen ? 'block' : 'hidden' " id='toggleMe'>
      <div id="class-metadata">
        
        
<div id="parent-class-section" class="nav-section">
  <h3>Parent</h3>

  <p class="link">Object
</div>

        
        
        
<!-- Method Quickref -->
<div id="method-list-section" class="nav-section">
  <h3>Methods</h3>

  <ul class="link-list" role="directory">
    <li ><a href="#method-c-new">::new</a>
    <li ><a href="#method-i-call">#call</a>
    <li ><a href="#method-i-need_gvl-3F">#need_gvl?</a>
    <li ><a href="#method-i-to_i">#to_i</a>
    <li ><a href="#method-i-to_proc">#to_proc</a>
  </ul>
</div>

      </div>
     </div>
    </nav>


    <div id='extraz'><div class='adzbox-index'  >
      
     </div>         
    </div>

    <main role="main" aria-labelledby="class-Fiddle::Function">
    <h1 id="class-Fiddle::Function" class="class">
      class Fiddle::Function
    </h1>

    <section class="description">
    
<h2 id="class-Fiddle::Function-label-Description">Description<span><a href="#class-Fiddle::Function-label-Description">&para;</a> <a href="#top">&uarr;</a></span></h2>

<p>A representation of a C function</p>

<h2 id="class-Fiddle::Function-label-Examples">Examples<span><a href="#class-Fiddle::Function-label-Examples">&para;</a> <a href="#top">&uarr;</a></span></h2>

<h3 id="class-Fiddle::Function-label-27strcpy-27">‘strcpy’<span><a href="#class-Fiddle::Function-label-27strcpy-27">&para;</a> <a href="#top">&uarr;</a></span></h3>

<pre>@libc = Fiddle.dlopen &quot;/lib/libc.so.6&quot;
   #=&gt; #&lt;Fiddle::Handle:0x00000001d7a8d8&gt;
f = Fiddle::Function.new(
  @libc[&#39;strcpy&#39;],
  [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP],
  Fiddle::TYPE_VOIDP)
   #=&gt; #&lt;Fiddle::Function:0x00000001d8ee00&gt;
buff = &quot;000&quot;
   #=&gt; &quot;000&quot;
str = f.call(buff, &quot;123&quot;)
   #=&gt; #&lt;Fiddle::Pointer:0x00000001d0c380 ptr=0x000000018a21b8 size=0 free=0x00000000000000&gt;
str.to_s
=&gt; &quot;123&quot;</pre>

<h3 id="class-Fiddle::Function-label-ABI+check">ABI check<span><a href="#class-Fiddle::Function-label-ABI+check">&para;</a> <a href="#top">&uarr;</a></span></h3>

<pre class="ruby"><span class="ruby-ivar">@libc</span> = <span class="ruby-constant">Fiddle</span>.<span class="ruby-identifier">dlopen</span> <span class="ruby-string">&quot;/lib/libc.so.6&quot;</span>
   <span class="ruby-comment">#=&gt; #&lt;Fiddle::Handle:0x00000001d7a8d8&gt;</span>
<span class="ruby-identifier">f</span> = <span class="ruby-constant">Fiddle</span><span class="ruby-operator">::</span><span class="ruby-constant">Function</span>.<span class="ruby-identifier">new</span>(<span class="ruby-ivar">@libc</span>[<span class="ruby-string">&#39;strcpy&#39;</span>], [<span class="ruby-constant">TYPE_VOIDP</span>, <span class="ruby-constant">TYPE_VOIDP</span>], <span class="ruby-constant">TYPE_VOIDP</span>)
   <span class="ruby-comment">#=&gt; #&lt;Fiddle::Function:0x00000001d8ee00&gt;</span>
<span class="ruby-identifier">f</span>.<span class="ruby-identifier">abi</span> <span class="ruby-operator">==</span> <span class="ruby-constant">Fiddle</span><span class="ruby-operator">::</span><span class="ruby-constant">Function</span><span class="ruby-operator">::</span><span class="ruby-constant">DEFAULT</span>
   <span class="ruby-comment">#=&gt; true</span>
</pre>

    </section>

      <section id="5Buntitled-5D" class="documentation-section">


      <section class="constants-list">
      <header>
      <h3>Constants</h3>
      </header>
      <dl>
          <dt id="DEFAULT">DEFAULT
          <dd><p><a href="Function.html#DEFAULT"><code>DEFAULT</code></a></p>

<p>Default ABI</p>
          <dt id="STDCALL">STDCALL
          <dd><p><a href="Function.html#STDCALL"><code>STDCALL</code></a></p>

<p>FFI implementation of WIN32 stdcall convention</p>
        </dl>
        </section>

        <section class="attribute-method-details" class="method-section">
        <header>
        <h3>Attributes</h3>
        </header>

          <div id="attribute-i-abi" class="method-detail">
            <div class="method-heading attribute-method-heading">
              <span class="method-name">abi</span><span
                class="attribute-access-type">[R]</span>
            </div>

            <div class="method-description">
              <p>The ABI of the <a href="Function.html"><code>Function</code></a>.</p>
              </div>
            </div>
          <div id="attribute-i-name" class="method-detail">
            <div class="method-heading attribute-method-heading">
              <span class="method-name">name</span><span
                class="attribute-access-type">[R]</span>
            </div>

            <div class="method-description">
              <p>The name of this function</p>
              </div>
            </div>
          <div id="attribute-i-ptr" class="method-detail">
            <div class="method-heading attribute-method-heading">
              <span class="method-name">ptr</span><span
                class="attribute-access-type">[R]</span>
            </div>

            <div class="method-description">
              <p>The address of this function</p>
              </div>
            </div>
            </section>


                <section id="public-class-5Buntitled-5D-method-details" class="method-section">
                <header>
                <h3>Public Class Methods</h3>
                </header>

                  <div id="method-c-new" class="method-detail ">
                      <div class="method-heading">
                        <span class="method-callseq">
                          new(ptr,
                              </span>
                              <span class="method-click-advice">click to toggle source</span>
                            </div>
                      <div class="method-heading">
                        <span class="method-callseq">
                          args,
                              </span>
                            </div>
                      <div class="method-heading">
                        <span class="method-callseq">
                          ret_type,
                              </span>
                            </div>
                      <div class="method-heading">
                        <span class="method-callseq">
                          abi = DEFAULT,
                              </span>
                            </div>
                      <div class="method-heading">
                        <span class="method-callseq">
                          name: nil,
                              </span>
                            </div>
                      <div class="method-heading">
                        <span class="method-callseq">
                          need_gvl: false)
                              </span>
                            </div>

                            <div class="method-description">
                              <p>Constructs a <a href="Function.html"><code>Function</code></a> object.</p>
<ul><li>
<p><code>ptr</code> is a referenced function, of a <a href="Handle.html"><code>Fiddle::Handle</code></a></p>
</li><li>
<p><code>args</code> is an Array of arguments, passed to the <code>ptr</code> function</p>
</li><li>
<p><code>ret_type</code> is the return type of the function</p>
</li><li>
<p><code>abi</code> is the ABI of the function</p>
</li><li>
<p><code>name</code> is the name of the function</p>
</li><li>
<p><code>need_gvl</code> is whether GVL is needed to call the function</p>
</li></ul>

                              <div class="method-source-code" id="new-source">
            <pre>static VALUE
initialize(int argc, VALUE argv[], VALUE self)
{
    ffi_cif * cif;
    VALUE ptr, arg_types, ret_type, abi, kwargs;
    VALUE name = Qnil;
    VALUE need_gvl = Qfalse;
    int c_ret_type;
    bool is_variadic = false;
    ffi_abi c_ffi_abi;
    void *cfunc;

    rb_scan_args(argc, argv, &quot;31:&quot;, &amp;ptr, &amp;arg_types, &amp;ret_type, &amp;abi, &amp;kwargs);
    rb_iv_set(self, &quot;@closure&quot;, ptr);

    if (!NIL_P(kwargs)) {
        enum {
            kw_name,
            kw_need_gvl,
            kw_max_,
        };
        static ID kw[kw_max_];
        VALUE args[kw_max_];
        if (!kw[0]) {
            kw[kw_name] = rb_intern_const(&quot;name&quot;);
            kw[kw_need_gvl] = rb_intern_const(&quot;need_gvl&quot;);
        }
        rb_get_kwargs(kwargs, kw, 0, kw_max_, args);
        if (args[kw_name] != Qundef) {
            name = args[kw_name];
        }
        if (args[kw_need_gvl] != Qundef) {
            need_gvl = args[kw_need_gvl];
        }
    }
    rb_iv_set(self, &quot;@name&quot;, name);
    rb_iv_set(self, &quot;@need_gvl&quot;, need_gvl);

    ptr = rb_Integer(ptr);
    cfunc = NUM2PTR(ptr);
    PTR2NUM(cfunc);
    c_ffi_abi = NIL_P(abi) ? FFI_DEFAULT_ABI : NUM2INT(abi);
    abi = INT2FIX(c_ffi_abi);
    ret_type = rb_fiddle_type_ensure(ret_type);
    c_ret_type = NUM2INT(ret_type);
    (void)INT2FFI_TYPE(c_ret_type); /* raise */
    ret_type = INT2FIX(c_ret_type);

    arg_types = normalize_argument_types(&quot;argument types&quot;,
                                         arg_types,
                                         &amp;is_variadic);
#ifndef HAVE_FFI_PREP_CIF_VAR
    if (is_variadic) {
        rb_raise(rb_eNotImpError,
                 &quot;ffi_prep_cif_var() is required in libffi &quot;
                 &quot;for variadic arguments&quot;);
    }
#endif

    rb_iv_set(self, &quot;@ptr&quot;, ptr);
    rb_iv_set(self, &quot;@argument_types&quot;, arg_types);
    rb_iv_set(self, &quot;@return_type&quot;, ret_type);
    rb_iv_set(self, &quot;@abi&quot;, abi);
    rb_iv_set(self, &quot;@is_variadic&quot;, is_variadic ? Qtrue : Qfalse);

    TypedData_Get_Struct(self, ffi_cif, &amp;function_data_type, cif);
    cif-&gt;arg_types = NULL;

    return self;
}</pre>
                              </div>
                            </div>


                          </div>

                          </section>

                <section id="public-instance-5Buntitled-5D-method-details" class="method-section">
                <header>
                <h3>Public Instance Methods</h3>
                </header>

                  <div id="method-i-call" class="method-detail ">
                            <div class="method-heading">
                              <span class="method-name">call</span><span
                                class="method-args">(*args)</span>
                              <span class="method-click-advice">click to toggle source</span>
                            </div>

                            <div class="method-description">
                              <p>Calls the constructed <a href="Function.html"><code>Function</code></a>, with <code>args</code>. Caller must ensure the underlying function is called in a thread-safe manner if running in a multi-threaded process.</p>

<p>Note that it is not thread-safe to use this method to directly or indirectly call many Ruby C-extension APIs unless you don’t pass +need_gvl: true+ to Fiddle::Function#new.</p>

<p>For an example see <a href="Function.html"><code>Fiddle::Function</code></a></p>

                              <div class="method-source-code" id="call-source">
            <pre>static VALUE
function_call(int argc, VALUE argv[], VALUE self)
{
    struct nogvl_ffi_call_args args = { 0 };
    fiddle_generic *generic_args;
    VALUE cfunc;
    VALUE abi;
    VALUE arg_types;
    VALUE cPointer;
    VALUE is_variadic;
    VALUE need_gvl;
    int n_arg_types;
    int n_fixed_args = 0;
    int n_call_args = 0;
    int i;
    int i_call;
    VALUE converted_args = Qnil;
    VALUE alloc_buffer = 0;

    cfunc    = rb_iv_get(self, &quot;@ptr&quot;);
    abi      = rb_iv_get(self, &quot;@abi&quot;);
    arg_types = rb_iv_get(self, &quot;@argument_types&quot;);
    cPointer = rb_const_get(mFiddle, rb_intern(&quot;Pointer&quot;));
    is_variadic = rb_iv_get(self, &quot;@is_variadic&quot;);
    need_gvl = rb_iv_get(self, &quot;@need_gvl&quot;);

    n_arg_types = RARRAY_LENINT(arg_types);
    n_fixed_args = n_arg_types;
    if (RTEST(is_variadic)) {
        if (argc &lt; n_arg_types) {
            rb_error_arity(argc, n_arg_types, UNLIMITED_ARGUMENTS);
        }
        if (((argc - n_arg_types) % 2) != 0) {
            rb_raise(rb_eArgError,
                     &quot;variadic arguments must be type and value pairs: &quot;
                     &quot;%&quot;PRIsVALUE,
                     rb_ary_new_from_values(argc, argv));
        }
        n_call_args = n_arg_types + ((argc - n_arg_types) / 2);
    }
    else {
        if (argc != n_arg_types) {
            rb_error_arity(argc, n_arg_types, n_arg_types);
        }
        n_call_args = n_arg_types;
    }
    Check_Max_Args(&quot;the number of arguments&quot;, n_call_args);

    TypedData_Get_Struct(self, ffi_cif, &amp;function_data_type, args.cif);

    if (is_variadic &amp;&amp; args.cif-&gt;arg_types) {
        xfree(args.cif-&gt;arg_types);
        args.cif-&gt;arg_types = NULL;
    }

    if (!args.cif-&gt;arg_types) {
        VALUE fixed_arg_types = arg_types;
        VALUE return_type;
        int c_return_type;
        ffi_type *ffi_return_type;
        ffi_type **ffi_arg_types;
        ffi_status result;

        arg_types = rb_ary_dup(fixed_arg_types);
        for (i = n_fixed_args; i &lt; argc; i += 2) {
          VALUE arg_type = argv[i];
          int c_arg_type;
          arg_type = rb_fiddle_type_ensure(arg_type);
          c_arg_type = NUM2INT(arg_type);
          (void)INT2FFI_TYPE(c_arg_type); /* raise */
          rb_ary_push(arg_types, INT2FIX(c_arg_type));
        }

        return_type = rb_iv_get(self, &quot;@return_type&quot;);
        c_return_type = FIX2INT(return_type);
        ffi_return_type = INT2FFI_TYPE(c_return_type);

        ffi_arg_types = xcalloc(n_call_args + 1, sizeof(ffi_type *));
        for (i_call = 0; i_call &lt; n_call_args; i_call++) {
            VALUE arg_type;
            int c_arg_type;
            arg_type = RARRAY_AREF(arg_types, i_call);
            c_arg_type = FIX2INT(arg_type);
            ffi_arg_types[i_call] = INT2FFI_TYPE(c_arg_type);
        }
        ffi_arg_types[i_call] = NULL;

        if (is_variadic) {
#ifdef HAVE_FFI_PREP_CIF_VAR
            result = ffi_prep_cif_var(args.cif,
                                      FIX2INT(abi),
                                      n_fixed_args,
                                      n_call_args,
                                      ffi_return_type,
                                      ffi_arg_types);
#else
            /* This code is never used because ffi_prep_cif_var()
             * availability check is done in #initialize. */
            result = FFI_BAD_TYPEDEF;
#endif
        }
        else {
            result = ffi_prep_cif(args.cif,
                                  FIX2INT(abi),
                                  n_call_args,
                                  ffi_return_type,
                                  ffi_arg_types);
        }
        if (result != FFI_OK) {
            xfree(ffi_arg_types);
            args.cif-&gt;arg_types = NULL;
            rb_raise(rb_eRuntimeError, &quot;error creating CIF %d&quot;, result);
        }
    }

    generic_args = ALLOCV(alloc_buffer,
                          sizeof(fiddle_generic) * n_call_args +
                          sizeof(void *) * (n_call_args + 1));
    args.values = (void **)((char *)generic_args +
                            sizeof(fiddle_generic) * n_call_args);

    for (i = 0, i_call = 0;
         i &lt; argc &amp;&amp; i_call &lt; n_call_args;
         i++, i_call++) {
        VALUE arg_type;
        int c_arg_type;
        VALUE original_src;
        VALUE src;
        arg_type = RARRAY_AREF(arg_types, i_call);
        c_arg_type = FIX2INT(arg_type);
        if (i &gt;= n_fixed_args) {
            i++;
        }
        src = argv[i];

        if (c_arg_type == TYPE_VOIDP) {
            if (NIL_P(src)) {
                src = INT2FIX(0);
            }
            else if (cPointer != CLASS_OF(src)) {
                src = rb_funcall(cPointer, rb_intern(&quot;[]&quot;), 1, src);
                if (NIL_P(converted_args)) {
                    converted_args = rb_ary_new();
                }
                rb_ary_push(converted_args, src);
            }
            src = rb_Integer(src);
        }

        original_src = src;
        VALUE2GENERIC(c_arg_type, src, &amp;generic_args[i_call]);
        if (src != original_src) {
            if (NIL_P(converted_args)) {
                converted_args = rb_ary_new();
            }
            rb_ary_push(converted_args, src);
        }
        args.values[i_call] = (void *)&amp;generic_args[i_call];
    }
    args.values[i_call] = NULL;
    args.fn = (void(*)(void))NUM2PTR(cfunc);

    if (RTEST(need_gvl)) {
        ffi_call(args.cif, args.fn, &amp;(args.retval), args.values);
    }
    else {
        (void)rb_thread_call_without_gvl(nogvl_ffi_call, &amp;args, 0, 0);
    }

    {
        int errno_keep = errno;
#if defined(_WIN32)
        DWORD error = WSAGetLastError();
        int socket_error = WSAGetLastError();
        rb_funcall(mFiddle, rb_intern(&quot;win32_last_error=&quot;), 1,
                   ULONG2NUM(error));
        rb_funcall(mFiddle, rb_intern(&quot;win32_last_socket_error=&quot;), 1,
                   INT2NUM(socket_error));
#endif
        rb_funcall(mFiddle, rb_intern(&quot;last_error=&quot;), 1, INT2NUM(errno_keep));
    }

    ALLOCV_END(alloc_buffer);

    return GENERIC2VALUE(rb_iv_get(self, &quot;@return_type&quot;), args.retval);
}</pre>
                              </div>
                            </div>


                          </div>

                  <div id="method-i-need_gvl-3F" class="method-detail ">
                            <div class="method-heading">
                              <span class="method-name">need_gvl?</span><span
                                class="method-args">()</span>
                              <span class="method-click-advice">click to toggle source</span>
                            </div>

                            <div class="method-description">
                              <p>Whether GVL is needed to call this function</p>

                              <div class="method-source-code" id="need_gvl-3F-source">
            <pre><span class="ruby-comment"># File fiddle/lib/fiddle/function.rb, line 14</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">need_gvl?</span>
  <span class="ruby-ivar">@need_gvl</span>
<span class="ruby-keyword">end</span></pre>
                              </div>
                            </div>


                          </div>

                  <div id="method-i-to_i" class="method-detail ">
                            <div class="method-heading">
                              <span class="method-name">to_i</span><span
                                class="method-args">()</span>
                              <span class="method-click-advice">click to toggle source</span>
                            </div>

                            <div class="method-description">
                              <p>The integer memory location of this function</p>

                              <div class="method-source-code" id="to_i-source">
            <pre><span class="ruby-comment"># File fiddle/lib/fiddle/function.rb, line 19</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">to_i</span>
  <span class="ruby-identifier">ptr</span>.<span class="ruby-identifier">to_i</span>
<span class="ruby-keyword">end</span></pre>
                              </div>
                            </div>


                          </div>

                  <div id="method-i-to_proc" class="method-detail ">
                            <div class="method-heading">
                              <span class="method-name">to_proc</span><span
                                class="method-args">()</span>
                              <span class="method-click-advice">click to toggle source</span>
                            </div>

                            <div class="method-description">
                              <p>Turn this function in to a proc</p>

                              <div class="method-source-code" id="to_proc-source">
            <pre><span class="ruby-comment"># File fiddle/lib/fiddle/function.rb, line 24</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">to_proc</span>
  <span class="ruby-identifier">this</span> = <span class="ruby-keyword">self</span>
  <span class="ruby-identifier">lambda</span> { <span class="ruby-operator">|</span><span class="ruby-operator">*</span><span class="ruby-identifier">args</span><span class="ruby-operator">|</span> <span class="ruby-identifier">this</span>.<span class="ruby-identifier">call</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">args</span>) }
<span class="ruby-keyword">end</span></pre>
                              </div>
                            </div>


                          </div>

                          </section>

              </section>
              </main>



            </div>  <!--  class='wrapper hdiv' -->


<footer id="validator-badges" role="contentinfo">
<p><a href="https://validator.w3.org/check/referer">Validate</a></p>
<p>Generated by <a href="https://ruby.github.io/rdoc/">RDoc</a> 6.4.0.</p>
<p>Based on <a href="https://github.com/ged/darkfish/">Darkfish</a> by <a href="http://deveiate.org">Michael Granger</a>.</p>

  
    <p><p><a href="https://ruby-doc.org">Ruby-doc.org</a> is a service of <a href="https://jamesbritt.com">James Britt</a> and <a href="https://neurogami.com">Neurogami</a>, purveyors of fine <a href='https://jamesbritt.bandcamp.com/'>dance noise</a></p>
</p>
  
  </footer>

<script type="text/javascript">


  let ads  = $("#carbonads-container").children().detach();


  function swapMode() {
    var cookieName = 'darkmode';
    var cssDarkmode = Cookies.get(cookieName);
    console.log("***** swapMode! " + cssDarkmode + " *****");


    if (cssDarkmode == "true") {
      console.log("We have dark mode, set the css to light ...");
      $('#rdoccss').attr("href", defaultModeCssHref);
      $('#cssSelect').text("Dark mode");
      cssDarkmode = "false";
      console.log("swapMode! Now set cookie to " + cssDarkmode);
      Cookies.set(cookieName, cssDarkmode);

    } else {
      console.log("We not have dark mode, set the css to dark ...");
      $('#rdoccss').attr("href", darkModeCsseHref);
      $('#cssSelect').text("Light mode");
      cssDarkmode = "true";
      console.log("swapMode! Now set cookie to " + cssDarkmode);
      Cookies.set(cookieName, cssDarkmode);

    }

    console.log("  --------------- ");
  }


const vueCssApp = new Vue({
el: '#menubar',
data: {
isDark: false
},
methods: {
toggleClass: function(event){
this.isDark = !this.isDark;
}
}
})

const vueApp = new Vue({
el: '#vapp',
data: { 
isOpen: true
},

mounted() {
this.handleResize();
this.manage_mob_classes();
window.addEventListener('resize', this.handleResize)
//this.isOpen !=  (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent));
},
destroyed() {
window.removeEventListener('resize', this.handleResize)
},
created() {
//manage_mob_classes();
},

methods : {
isMobile() {
  return (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent));
},

  handleResize() {
    if (!this.isMobile()) {
      this.isOpen = window.innerWidth > 800;
    }
  },

  manage_mob_classes() {
    if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
      $("nav").addClass("mob_nav");
      $("main").addClass("mob_main");
      $("#extraz").addClass("mob_extraz");
      $("#carbonads-container").addClass("mob_carbonads-container");
      this.isOpen  = false;
    } else {
      $("nav").removeClass("mob_nav") 
        $("main").removeClass("mob_main");
      $("#extraz").removeClass("mob_extraz");
      $("#carbonads-container").removeClass("mob_carbonads-container");
      this.isOpen  = true;
    }
  },

  toggleNav() {
    this.isOpen =! this.isOpen ;
    // alert("Toggle nav!");
    console.log("toggleNav() click: " + this.isOpen );
  }
}
})

$("#carbonads-container").append(ads);


$(function() {

    var darkmode = Cookies.get("darkmode");
    console.log("Document ready: " + darkmode);

    if ( darkmode  == "true" ) {
      $('#cssSelect').text("Light mode");
    } else {
      $('#cssSelect').text("Dark mode");
     }

    $('body').css('display','block');
    });

</script>

    
  </body> 
</html>

